package com.yuju.common.util.http;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

import com.alibaba.fastjson.JSONObject;

/**
 * HttpWrapper
 * Http请求对象和响应对象的封装
 * 封装Http请求和响应
 * @author xue
 * @date 2017-01-07
 */
public class HttpWrapper {

	/** HTTP GET method */
	public static final String METHOD_GET = "GET";

	/** HTTP POST method */
	public static final String METHOD_POST = "POST";

	/**
	 * 待请求的url
	 */
	private String url = null;

	/**
	 * 默认的请求方式
	 */
	private String method = METHOD_POST;

	private int timeout = 0;

	private int connectionTimeout = 0;

	/**
	 * Post方式请求时组装好的参数值对
	 */
	// private NameValuePair[] parameters = null;
	
	private List<NameValuePair> parameters = null;

	/**
	 * Get方式请求时对应的参数
	 */
	private String queryString = null;

	/**
	 * 默认的请求编码方式
	 */
	private String charset = "UTF-8";

	/**
	 * 请求发起方的ip地址
	 */
	private String clientIp;

	/**
	 * 请求返回的方式
	 */
	private HttpResultType resultType = HttpResultType.BYTES;
	
	private HttpServletRequest request;
	
	private HttpServletResponse response;
	
	private String servletPath;

	private static final String SESSION_UNIQUE_CODE = "JSESSIONID";
	private static final String TOKEN_NAME = "token";
	
	private String tokenName; // 存储的token名称
	private String tokenVal; // 存储的token值
	
	private String protocol; // 访问前缀
	private String serverHost; // 域名
	private String port; // 端口
	private String serverContext; // 应用名
	private String action; // 请求的action
	
	private Map<String, Object> headers; // 请求头
	
	private JSONObject json; // JSON参数
	
	private String param; // 字符串参数

	public HttpWrapper(HttpResultType resultType) {
		super();
		this.resultType = resultType;
	}
	
	public HttpWrapper(HttpServletRequest request, HttpServletResponse response) {
		this.request = request;
		this.response = response;
		initWithServletContext();
	}
	
	public HttpWrapper(String method, String protocol, String serverHost, String port, String serverContext) {
		initRequestMethod(method);
		this.protocol = protocol;
		this.serverHost = serverHost;
		this.port = port;
		this.serverContext = serverContext;
		this.initToken();
	}
	
	/**
	 * 添加参数
	 * @author xue
	 * @date 2017-01-09
	 * @param params 参数集
	 */
	public void addParams(Map<String, String> params) {
		this.initRequestParameters(params);
	}
	
	/**
	 * 
	 * 功能：添加JSON参数<br/>
	 *
	 * @author xuehj
	 * @Date 2018年1月29日 下午3:41:42 <br/>
	 */
	public void addJson(JSONObject param) {
		this.json = param;
	}
	
	/**
	 * 初始化token
	 * @author xue
	 * @date 2017-01-07
	 */
	private void initToken() {
		if (this.tokenName == null)
			this.tokenName = "token";
		if (null != this.tokenName && !"".equals(this.tokenName)) {
			this.tokenVal = HttpClientCookieManager.getToken(this.tokenName);
		}
	}
	
	/**
	 * 初始化
	 * @author xue
	 * @date 2017-01-07
	 */
	private void initWithServletContext() {
		this.initRequestMethod();
		this.initRequestParameters();
		
		this.servletPath = this.request.getServletPath();
		this.url = getProtocol() + "://" + getServerHost();
		if (StringUtils.isEmpty(getPort())) {
			this.url = this.url + "/" + getServerContext() + servletPath;
		} else {
			this.url = this.url + ":" + getPort() + "/"+ getServerContext() + servletPath;
		}
		
		this.tokenName = this.request.getParameter(getTokenName()); // this.getParameter().get(ConfigUtil.getSessionUniqueCode());
		
		if (null != this.tokenName && !"".equals(this.tokenName)) {
			this.tokenVal = HttpClientCookieManager.getToken(this.tokenName);
		}
	}

	/**
	 * 初始化请求方式
	 * @author xue
	 * @date 2017-01-07
	 */
	private void initRequestMethod() {
		if(HttpWrapper.METHOD_GET.equals(request.getMethod())) {
			this.method = HttpWrapper.METHOD_GET;
		} else {
			this.method = HttpWrapper.METHOD_POST;
		}
	}

	/**
	 * 初始化请求方式
	 * @author xue
	 * @date 2017-01-07
	 */
	private void initRequestMethod(String method) {
		if (HttpWrapper.METHOD_GET.equalsIgnoreCase(method)) {
			this.method = HttpWrapper.METHOD_GET;
		} else if (HttpWrapper.METHOD_POST.equalsIgnoreCase(method))  {
			this.method = HttpWrapper.METHOD_POST;
		}
	}
	
	/**
	 * 初始化请求参数
	 * @author xue
	 * @date 2017-01-07
	 */
	private void initRequestParameters() {
		if(this.method == HttpWrapper.METHOD_GET) {
			String queryString = this.request.getQueryString();
			if(StringUtils.isNotEmpty(queryString)) {
				this.queryString = queryString;
			}
		} else {
			Map<String, String> paramsMap = getParameter();
			this.parameters = new ArrayList<NameValuePair>();
	        for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
	        	this.parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
	        }
		}
	}
	
	/**
	 * 初始化请求参数
	 * @author xue
	 * @date 2017-01-07
	 */
	private void initRequestParameters(Map<String, String> params) {
		if (params == null || params.size() == 0)
			return ;
		
		if(this.method == HttpWrapper.METHOD_GET) {
			StringBuffer queryString = new StringBuffer();
			for (Map.Entry<String, String> entry : params.entrySet()) {
				queryString.append(entry.getKey()).append("=").append(entry.getValue());
				queryString.append("&");
	        }
			if(queryString.length() > 0) {
				this.queryString = queryString.substring(0, queryString.length() - 1);
			}
		} else {
			this.parameters = new ArrayList<NameValuePair>();
	        for (Map.Entry<String, String> entry : params.entrySet()) {
	        	this.parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
	        }
		}
	}

	/**
	 * 将request中的Map<String, String[]>转化为Map<String, String>
	 * @author xue
	 * @date 2017-01-07
	 * @return
	 */
	public Map<String, String> getParameter() {
		Map<String, String[]> paraMap = this.request.getParameterMap();
		Map<String, String> returnMap = new HashMap<String, String>();
		Iterator<Entry<String, String[]>> entries = paraMap.entrySet().iterator();
		Entry<String, String[]> entry;
		while(entries.hasNext()) {
			entry = entries.next();
			String key = entry.getKey();
			String[] val = entry.getValue();
			String valStr = null;
			if(null == val) {
				valStr = "";
			} else {
				valStr = val[0];
			}
			returnMap.put(key, valStr);
		}
		return returnMap;
	}

	public String getProtocol() {
		return this.protocol;
	}

	public void setProtocol(String protocol) {
		this.protocol = protocol;
	}

	public String getServerHost() {
		return this.serverHost;
	}

	public void setServerHost(String serverHost) {
		this.serverHost = serverHost;
	}

	public String getPort() {
		return this.port;
	}

	public void setPort(String port) {
		// TODO Auto-generated method stub
		this.port = port;
	}
	
	public String getServerContext() {
		// TODO Auto-generated method stub
		return this.serverContext;
	}
	
	public void setServerContext(String serverContext) {
		// TODO Auto-generated method stub
		this.serverContext = serverContext;
	}
	
	/**
	 * 响应到页面
	 * @author xue
	 * @date 2016-01-07
	 * @param content 响应的内容
	 * @throws IOException
	 */
	public void response(String content) throws IOException {
		PrintWriter out = this.response.getWriter();
		out.write(content);
		out.flush();
		out.close();
	}

	/**
	 * 响应到页面
	 * @author xue
	 * @date 2016-01-07
	 * @param content 响应的内容
	 * @throws Exception
	 */
	public void handleResponse(IHttpClientCallBack iccb, String content) throws Exception {
		iccb.execute(content);
	}

	/**
	 * 响应到页面
	 * @author xue
	 * @date 2016-01-07
	 * @param content 响应的内容
	 * @throws Exception
	 */
	public void handleResponse(String content) throws Exception {
	}

	/**
	 * @return Returns the clientIp.
	 */
	public String getClientIp() {
		return clientIp;
	}

	/**
	 * @param clientIp
	 *            The clientIp to set.
	 */
	public void setClientIp(String clientIp) {
		this.clientIp = clientIp;
	}

	public List<NameValuePair> getParameters() {
		return parameters;
	}

	public void setParameters(List<NameValuePair> parameters) {
		this.parameters = parameters;
	}

	public String getQueryString() {
		return queryString;
	}

	public void setQueryString(String queryString) {
		this.queryString = queryString;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getMethod() {
		return method;
	}

	public void setMethod(String method) {
		this.method = method;
	}

	public int getConnectionTimeout() {
		return connectionTimeout;
	}

	public void setConnectionTimeout(int connectionTimeout) {
		this.connectionTimeout = connectionTimeout;
	}

	public int getTimeout() {
		return timeout;
	}

	public void setTimeout(int timeout) {
		this.timeout = timeout;
	}

	/**
	 * @return Returns the charset.
	 */
	public String getCharset() {
		return charset;
	}

	/**
	 * @param charset
	 *            The charset to set.
	 */
	public void setCharset(String charset) {
		this.charset = charset;
	}

	public HttpResultType getResultType() {
		return resultType;
	}

	public void setResultType(HttpResultType resultType) {
		this.resultType = resultType;
	}

	public HttpServletRequest getRequest() {
		return request;
	}

	public void setRequest(HttpServletRequest request) {
		this.request = request;
	}

	public HttpServletResponse getResponse() {
		return response;
	}

	public void setResponse(HttpServletResponse response) {
		this.response = response;
	}

	public String getServletPath() {
		return servletPath;
	}

	public void setServletPath(String servletPath) {
		this.servletPath = servletPath;
	}

	public String getTokenName() {
		return tokenName;
	}

	public void setTokenName(String tokenName) {
		this.tokenName = tokenName;
	}

	public String getTokenVal() {
		return tokenVal;
	}

	public void setTokenVal(String tokenVal) {
		this.tokenVal = tokenVal;
	}

	public String getAction() {
		return action;
	}

	public Map<String, Object> getHeaders() {
		return headers;
	}

	public void setHeaders(Map<String, Object> headers) {
		this.headers = headers;
	}

	public JSONObject getJsonParam() {
		return json;
	}

	public String getParam() {
		return param;
	}

	public void setParam(String param) {
		this.param = param;
	}

	public void setAction(String action) {
		this.action = action;
		this.url = this.getProtocol() + "://" + this.getServerHost();
		if (StringUtils.isEmpty(this.getPort())) {
			if (this.serverContext != null)
				if (this.action != null)
					this.url = this.url + "/" + this.getServerContext() + "/" + this.action;
				else
					this.url = this.url + "/" + this.getServerContext();
			else
				if (this.action != null)
					this.url = this.url + "/" + this.action;
		} else {
			if (this.serverContext != null)
				if (this.action != null)
					this.url = this.url + ":" + this.getPort() + "/" + this.getServerContext() + "/" + this.action;
				else
					this.url = this.url + ":" + this.getPort() + "/" + this.getServerContext();
			else
				if (this.action != null)
					this.url = this.url + ":" + this.getPort() + "/" + this.action;
				else
					this.url = this.url + ":" + this.getPort();
		}
	}

}
